package com.lauor.smpedr.transaction.jdbc;

import com.lauor.smpedr.transaction.Transaction;
import com.lauor.smpedr.transaction.TransactionIsolationLevel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;

/**
 * jdbc事务
 */
public class JdbcTransaction implements Transaction {
    private final Logger LOG = LoggerFactory.getLogger(JdbcTransaction.class);

    protected Connection connection;

    protected DataSource dataSource;

    protected TransactionIsolationLevel transactionIsolationLevel;

    protected boolean autoCommit;

    protected boolean closed;

    public JdbcTransaction(Connection connection) {
        this.connection = connection;
    }

    public JdbcTransaction(DataSource dataSource, TransactionIsolationLevel transactionIsolationLevel, boolean autoCommit) {
        this.dataSource = dataSource;
        this.transactionIsolationLevel = transactionIsolationLevel;
        this.autoCommit = autoCommit;
    }

    @Override
    public Connection getConnection() throws SQLException {
        if (this.connection == null){
            this.openConnection();
        }
        return this.connection;
    }

    protected void openConnection() throws SQLException {
        if (this.dataSource == null) return;

        this.connection = this.dataSource.getConnection();
        if (this.connection == null) return;
        this.closed = false;
        //隔离级别
        if (this.transactionIsolationLevel != null && this.connection.getTransactionIsolation() != this.transactionIsolationLevel.getLevel()){
            this.connection.setTransactionIsolation( this.transactionIsolationLevel.getLevel() );
        }
        //自动提交
        this.setDesiredAutoCommit(this.autoCommit);
    }

    @Override
    public void commit() throws SQLException {
        if (this.connection != null && !this.connection.getAutoCommit()){
            this.connection.commit();
        }
    }

    @Override
    public void rollback() throws SQLException {
        if (this.connection != null && !this.connection.getAutoCommit()){
            this.connection.rollback();
        }
    }

    @Override
    public void close() throws SQLException {
        if (this.connection != null){
            this.resetAutoCommit();
        }
        this.connection.close();
        this.closed = true;
    }

    @Override
    public Integer getTimeout() {
        return null;
    }

    @Override
    public boolean isClosed() {
        return this.closed;
    }

    protected void resetAutoCommit(){
        try {
            if ( !this.connection.getAutoCommit() ){
                this.connection.setAutoCommit(true);
            }
        } catch (SQLException e) {
            LOG.info("Error resetting autocommit to true", e);
        }
    }

    protected void setDesiredAutoCommit(boolean desiredAutoCommit) throws SQLException {
        if (this.connection.getAutoCommit() != desiredAutoCommit){
            this.connection.setAutoCommit(desiredAutoCommit);
        }
    }
}
